package edu.kit.ksri.db.mturk.workerpools;

import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import edu.kit.ksri.db.mturk.connectionhandlers.AbstractWorkerManager;
import edu.kit.ksri.db.mturk.utils.CSVUtils;
import edu.kit.ksri.db.mturk.utils.FileUtils;
import edu.kit.ksri.db.mturk.var.ConnectionMode;
import edu.kit.ksri.db.mturk.var.Icd;
import edu.kit.ksri.db.mturk.var.StaticInformation;

/**
 * Copyright (c) 2010-2011 Karlsruhe Institute of Technology (KIT), Germany
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 * 
 * --------------------------------------------------------------------------
 * 
 * Software: CSP/WMV tool for dynamic quality management of microtasks
 * http://www.ksri.kit.edu/Upload/Users/PeopleClouds/HCOMP2011_An_extendable_toolkit_for_managing_quality_of_human-based_eServices.pdf
 * 
 * Organization: Karlsruhe Institute of Technology (KIT), Germany
 * http://www.kit.edu
 * 
 * Project: PeopleClouds project of the Karlsruhe Service Research Institute(KSRI)
 * http://www.ksri.kit.edu/Default.aspx?PageId=818
 * 
 * Contributing authors: David Bermbach, Sandra Rath, Pascal Wichmann, Robert Kern
 */
public class PoolManager {

	private static Logger basiclog = Logger.getLogger("basic."
			+ PoolManager.class);

	private static final Logger perflog = Logger.getLogger("perf."
			+ PoolManager.class);

	/** Singleton */
	private static final PoolManager instance = new PoolManager();

	/** the collection of pools running within this Java VM */
	private final HashMap<String, WorkerPool> pools = new HashMap<String, WorkerPool>();

	private PoolManager() {
	}

	/**
	 * 
	 * @return a new instance of {@link PoolManager}
	 */
	public static PoolManager getInstance() {
		return PoolManager.instance;
	}

	/**
	 * registers a worker pool, will never overwrite an existing pool unless it
	 * is empty.
	 * 
	 * @param wp
	 *            the pool to be added, may not be null
	 * @return true if registering was successful, false otherwise
	 */
	boolean registerNewPool(WorkerPool wp) {
		if (wp == null)
			return false;
		synchronized (pools) {
			WorkerPool old = pools.put(wp.getPoolName(), wp);
			if (old != null && old.size() > 0) {
				pools.put(old.getPoolName(), old);
				return false;
			}
			return true;
		}
	}

	/**
	 * deregisters a {@link WorkerPool}, will be denied unless a pool is empty
	 * 
	 * 
	 * @param pool
	 *            the pool which shall be deregistered
	 * @return true if the pool could be deregistered and is no longer
	 *         available, false otherwise. If the pool did not exist before, the
	 *         result is also true.
	 */
	public boolean deregisterWorkerPool(String pool) {
		synchronized (pools) {
			if (pools.get(pool).size() != 0)
				return false;
			pools.remove(pool);
			return true;
		}
	}

	/**
	 * 
	 * @param pool
	 * @return true if pool has already been registered as a worker pool.
	 */
	public boolean containsWorkerPool(String pool) {
		return pools.containsKey(pool);

	}

	/**
	 * 
	 * @param poolname
	 * @return the worker pool associated with the parameter. null otherwise.
	 */
	public WorkerPool getPoolForName(String poolname) {
		synchronized (pools) {
			return pools.get(poolname);
		}
	}

	@Override
	public String toString() {
		String s = "Managed Pools:";
		synchronized (pools) {
			for (WorkerPool wp : pools.values()) {
				s += "\n\t" + wp.getPoolName() + " (" + wp.size() + " workers)";
			}
		}
		return s;
	}

	/**
	 * creates a CSV file of the specified pool
	 * 
	 * @param poolname
	 *            pool which shall be exported
	 * @param filename
	 *            location and name of the CSV file
	 * @return true if export was successful, false otherwise
	 */
	@Deprecated
	public boolean exportPoolAsCSV(String poolname, String filename) {
		WorkerPool wp = this.getPoolForName(poolname);
		if (wp == null) {
			basiclog.error("Pool \"" + poolname + "\" does not exist.");
			return false;
		}
		if (filename == null) {
			basiclog.error("Parameter filename must not be null");
			return false;
		}
		String[] captions = new String[3];
		captions[0] = "Worker ID";
		captions[1] = "Correctness Level";
		captions[2] = "Next Inspection In";
		if (CSVUtils.toCSVFile(wp.getWorkerArray(), captions, filename)) {
			basiclog.info("Successfully exported worker pool \"" + poolname
					+ "\" to file " + filename + ".");
			return true;
		} else {
			basiclog.error("Could not export worker pool \"" + poolname
					+ "\" to file " + filename + ".");
			return false;
		}

	}

	/**
	 * convenience method. exports all pools to csv files of the name
	 * fileprefix-POOLNAME.csv
	 * 
	 * @see PoolManager.exportPoolAsCSV(String poolname, String filename)
	 * 
	 * @param fileprefix
	 * @return the number of pools which could not be exported, or 0 if
	 *         everything was okay. -1 is returned when the parameter is null.
	 */
	@Deprecated
	public int exportPoolsAsCSV(String fileprefix) {
		if (fileprefix == null) {
			basiclog.error("Parameter fileprefix must not be null");
			return -1;
		}
		Set<String> keys = null;
		synchronized (pools) {
			keys = pools.keySet();
		}
		int error = 0;
		for (String s : keys) {
			if (exportPoolAsCSV(s, fileprefix + "-" + s + ".csv"))
				continue;
			error++;
		}
		return error;
	}

	/**
	 * creates a CSV file of the specified pool
	 * 
	 * @param poolname
	 *            pool which shall be exported
	 * @param filename
	 *            location and name of the CSV file
	 * @return true if export was successful, false otherwise
	 */
	@Deprecated
	public boolean exportPoolAsSpaceDelimitedFile(String poolname,
			String filename) {
		WorkerPool wp = this.getPoolForName(poolname);
		if (wp == null) {
			basiclog.error("Pool \"" + poolname + "\" does not exist.");
			return false;
		}
		if (filename == null) {
			basiclog.error("Parameter filename must not be null");
			return false;
		}
		String[] captions = new String[3];
		captions[0] = "Worker ID";
		captions[1] = "Correctness Level";
		captions[2] = "Next Inspection In";
		String[][] temp = CSVUtils.combineStringArraysforToCSVWithCaptions(
				wp.getWorkerArray(), captions);
		if (FileUtils.writeToFile(temp, filename)) {
			basiclog.info("Successfully exported worker pool \"" + poolname
					+ "\" to file " + filename + ".");
			return true;
		} else {
			basiclog.error("Could not export worker pool \"" + poolname
					+ "\" to file " + filename + ".");
			return false;
		}

	}

	/**
	 * convenience method. exports all pools to csv files of the name
	 * fileprefix-POOLNAME.csv
	 * 
	 * @see PoolManager.exportPoolAsCSV(String poolname, String filename)
	 * 
	 * @param fileprefix
	 * @return the number of pools which could not be exported, or 0 if
	 *         everything was okay. -1 is returned when the parameter is null.
	 */
	@Deprecated
	public int exportPoolsAsSpaceDelimitedFile(String fileprefix) {
		if (fileprefix == null) {
			basiclog.error("Parameter fileprefix must not be null");
			return -1;
		}
		Set<String> keys = null;
		synchronized (pools) {
			keys = pools.keySet();
		}
		int error = 0;
		for (String s : keys) {
			if (exportPoolAsSpaceDelimitedFile(s, fileprefix + "-" + s + ".txt"))
				continue;
			error++;
		}
		return error;
	}

	/**
	 * exports all workers into the specified file
	 * 
	 * @param filename
	 * @return true if export was successful, false otherwise.
	 */
	@Deprecated
	public boolean persist(String filename) {
		synchronized (pools) {
			ObjectOutputStream oos = null;
			try {
				oos = new ObjectOutputStream(new FileOutputStream(filename));
				for (WorkerPool wp : pools.values()) {
					List<AbstractWorker> l = wp.getWorkers();
					oos.writeObject(wp.getPoolName());
					for (AbstractWorker w : l) {
						oos.writeObject(w);
					}
					basiclog.info("Persisted worker pool \"" + wp.getPoolName()
							+ "\".");
				}
				basiclog.info("Persisted all worker pools.");
				return true;
			} catch (Exception e) {
				basiclog.error("Error while persisting: " + e);
				return false;
			} finally {
				try {
					oos.close();
				} catch (IOException e) {
				}
			}
		}
	}

	/**
	 * imports the {@link WorkerPool}s from the specified file. Current pools
	 * are deleted first.
	 * 
	 * 
	 * @param filename
	 * @return true if import was succesful, false otherwise.
	 */
	@Deprecated
	public boolean importFromPersistedFile(String filename) {
		synchronized (pools) {
			pools.clear();
			ObjectInputStream ois = null;
			try {
				ois = new ObjectInputStream(new FileInputStream(filename));
				String poolname = null;
				while (true) {
					Object o = ois.readObject();
					if (o == null)
						break;
					if (o instanceof String) {
						poolname = (String) o;
						basiclog.info("Reading worker pool \"" + poolname
								+ "\".");
						WorkerPool.createNewWorkerPool(poolname, 0);
					} else if (o instanceof AbstractWorker) {
						AbstractWorker w = (AbstractWorker) o;
						pools.get(poolname).addWorker(w);
					} else {
						basiclog.error("Found unsupported object of typ "
								+ o.getClass().getName());
						return false;
					}

				}
				basiclog.info("Import succesful.");
				return true;
			} catch (EOFException eof) {
				basiclog.info("Import successful.");
				return true;
			} catch (Exception e) {
				basiclog.error("Error while importing: " + e);
				return false;
			} finally {
				try {
					ois.close();
				} catch (IOException e) {
				}
			}
		}
	}

	/**
	 * exports all currently known workers to a single file One worker per line,
	 * no other white spaces allowed.
	 * 
	 * The specified file will be overwritten
	 * 
	 * @param file
	 *            target file name
	 * @return whether the export was successful.
	 */
	public boolean exportWorkers(String file) {
		PrintWriter pw = null;
		try {
			
			//Please note: For the sake of simplicity the ICD scenario will only export the average labelling performance
			if (StaticInformation.scenario instanceof Icd) {
				pw = new PrintWriter(new File(file));
				pw.println("#POOLNAME,WORKER_ID," + "TOTAL_ASSIGNMENTS,"
						+ "SPECIFICITY," + "SENSITIVITY");
				for (String key : pools.keySet()) {
					WorkerPool wp = pools.get(key);
					synchronized (wp) {
						for (AbstractWorker w : wp.getWorkers()) {
							ICDWorker icdWorker = (ICDWorker) w;

							pw.println(key + "," + icdWorker.getWorkerId()
									+ "," + icdWorker.getTotalAssignments()
									+ "," + icdWorker.getAverageSpecificity() + ","
									+ icdWorker.getAverageSensitivity());
						}
					}
				}
				basiclog.info("Exported workers to file.");
				return true;
			}
			else{
//--------------Standard Worker--------------------			
				pw = new PrintWriter(new File(file));
				pw.println("#POOLNAME,WORKER_ID," + "TOTAL_ASSIGNMENTS,"
						+ "ASSIGNMENTS_INSPECTED_CORRECT,"
						+ "ASSIGNMENTS_INSPECTED_FALSE");
				for (String key : pools.keySet()) {
					WorkerPool wp = pools.get(key);
					synchronized (wp) {
						for (AbstractWorker w : wp.getWorkers()) {
							pw.println(key + "," + w.getWorkerId()
									+ "," + w.getTotalAssignments()
									+ ","
									+ w.getTotalInspectedCorrect()
									+ ","
									+ w.getTotalInspectedFalse());
						}
					}
				}
				basiclog.info("Exported workers to file.");
				return true;
			}
		} catch (Exception e) {
			basiclog.error("Could not export to file " + file
					+ " due to the following exception: " + e);
			return false;
		} finally {
			pw.flush();
			pw.close();
		}
	}

	/**
	 * 
	 * Imports the worker pools from a file, existing workers will not be
	 * overwritten. This method also assigns each worker the qualification
	 * associated with the respective pool as specified in
	 * {@link StaticInformation}. One worker per line, no other white spaces
	 * allowed.
	 * 
	 * @param file
	 *            the name of the input file
	 * @param createPools
	 *            whether non-existing pools shall be created or not.
	 * @return
	 */
	public boolean importWorkers(String file, boolean createPools) {
		try {
			WorkerPool.createNewWorkerPool("DELETED", 0);
		} catch (Exception e1) {
			if (getPoolForName("DELETED") == null) {
				basiclog.error("Could not create pool \"DELETED\".");
				return false;
			} else {
				basiclog.info("Could not create pool \"DELETED\""
						+ " because it already exists.");
			}
		}
		StringTokenizer st;
		String pool = null, id = null;

		AbstractWorker w = null;
		WorkerPool wp = null;
		// all workers which no longer exist will be moved to a new pool
		// "DELETED", the key is the respective worker, the value is the
		// respective pool name
		HashMap<AbstractWorker, String> deleted = new HashMap<AbstractWorker, String>();
		try {
			if (StaticInformation.scenario instanceof Icd) {
				int total = 0;
				double sensitivity = 0, specificity = 0;
				AbstractWorkerManager workerManager = AbstractWorkerManager
						.getInstance();
				BufferedReader br = new BufferedReader(new FileReader(file));
				String line = br.readLine();
				while (line != null) {
					if (line.startsWith("#") || line.trim().equals("")) {
						line = br.readLine();
						continue;
					}
					st = new StringTokenizer(line, ",");
					pool = st.nextToken();
					id = st.nextToken();
					total = Integer.parseInt(st.nextToken());
					specificity = Double.parseDouble(st.nextToken());
					sensitivity = Double.parseDouble(st.nextToken());

					w = new ICDWorker(id, total, specificity, sensitivity);

					wp = getPoolForName(pool);
					if (wp == null && createPools) {
						WorkerPool.createNewWorkerPool(pool, 0);
						wp = getPoolForName(pool);
					}
					wp.addWorker(w);
					Integer score = workerManager.getQualificationValue(id);
					if (pool.equals("ACTIVE")) {
						if (score != null
								&& score == StaticInformation.activePoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager.assignQualification(
								StaticInformation.scenario
										.getQualificationTypeID(), id,
								StaticInformation.activePoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.activePoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.activePoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.activePoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}

					} else if (pool.equals("PENDING")) {
						if (score != null
								&& score == StaticInformation.pendingPoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager
								.assignQualification(
										StaticInformation.scenario
												.getQualificationTypeID(),
										id,
										StaticInformation.pendingPoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.pendingPoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.pendingPoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.pendingPoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}
					} else if (pool.equals("BLOCKED")) {
						if (score != null
								&& score == StaticInformation.blockedPoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager
								.assignQualification(
										StaticInformation.scenario
												.getQualificationTypeID(),
										id,
										StaticInformation.blockedPoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.blockedPoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.blockedPoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.blockedPoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}
					}
					line = br.readLine();
				}
				WorkerPool del = getPoolForName("DELETED");
				for (AbstractWorker ww : deleted.keySet()) {
					perflog.info((del.addWorker(ww) ? "Added worker "
							+ ww.getWorkerId() + " to pool \"DELETED\"."
							: "Adding worker " + ww.getWorkerId()
									+ " to pool \"DELETED\" failed."));
					perflog.info((getPoolForName(deleted.get(ww)).removeWorker(
							ww) ? "Removed worker " + ww.getWorkerId()
							+ " from original pool."
							: "Could not remove worker " + ww.getWorkerId()
									+ " from original pool."));
				}

				return true;
			}else if (StaticInformation.scenario.getPrefix().equals("AddressResearch") && StaticInformation.scenario.getConnectionMode() == ConnectionMode.SIM){
//--------------Sim Worker--------------------
				
				basiclog.debug("Initializing SimWorker Pool");
				int total = 0, correct = 0, wrong = 0;
				AbstractWorkerManager workerManager = AbstractWorkerManager
						.getInstance();
				BufferedReader br = new BufferedReader(new FileReader(file));
				String line = br.readLine();
				while (line != null) {
					if (line.startsWith("#") || line.trim().equals("")) {
						line = br.readLine();
						continue;
					}
					st = new StringTokenizer(line, ",");
					pool = st.nextToken();
					id = st.nextToken();
					total = Integer.parseInt(st.nextToken());
					correct = Integer.parseInt(st.nextToken());
					wrong = Integer.parseInt(st.nextToken());
	
					w = new SimWorker(id, total, correct, wrong);
	
					wp = getPoolForName(pool);
					if (wp == null && createPools) {
						WorkerPool.createNewWorkerPool(pool, 0);
						wp = getPoolForName(pool);
					}
					wp.addWorker(w);
					Integer score = workerManager.getQualificationValue(id);
					if (pool.equals("ACTIVE")) {
						if (score != null
								&& score == StaticInformation.activePoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager.assignQualification(
								StaticInformation.scenario
										.getQualificationTypeID(), id,w.getCorrectnessLevel()<StaticInformation.minimumCorrectnessLevel?
												StaticInformation.pendingPoolQualificationValue:StaticInformation.activePoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.activePoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.activePoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.activePoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}
	
					} else if (pool.equals("PENDING")) {
						if (score != null
								&& score == StaticInformation.pendingPoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager
								.assignQualification(
										StaticInformation.scenario
												.getQualificationTypeID(),
										id,
										StaticInformation.pendingPoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.pendingPoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.pendingPoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.pendingPoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}
					} else if (pool.equals("BLOCKED")) {
						if (score != null
								&& score == StaticInformation.blockedPoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager
								.assignQualification(
										StaticInformation.scenario
												.getQualificationTypeID(),
										id,
										StaticInformation.blockedPoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.blockedPoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.blockedPoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.blockedPoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}
					}
					line = br.readLine();
				}
				WorkerPool del = getPoolForName("DELETED");
				for (AbstractWorker ww : deleted.keySet()) {
					perflog.info((del.addWorker(ww) ? "Added worker "
							+ ww.getWorkerId() + " to pool \"DELETED\"."
							: "Adding worker " + ww.getWorkerId()
									+ " to pool \"DELETED\" failed."));
					perflog.info((getPoolForName(deleted.get(ww)).removeWorker(
							ww) ? "Removed worker " + ww.getWorkerId()
							+ " from original pool."
							: "Could not remove worker " + ww.getWorkerId()
									+ " from original pool."));
				}
	
				return true;
			}else {
//--------------Standard Worker--------------------			
				int total = 0, correct = 0, wrong = 0;
				AbstractWorkerManager workerManager = AbstractWorkerManager
						.getInstance();
				BufferedReader br = new BufferedReader(new FileReader(file));
				String line = br.readLine();
				while (line != null) {
					if (line.startsWith("#") || line.trim().equals("")) {
						line = br.readLine();
						continue;
					}
					st = new StringTokenizer(line, ",");
					pool = st.nextToken();
					id = st.nextToken();
					total = Integer.parseInt(st.nextToken());
					correct = Integer.parseInt(st.nextToken());
					wrong = Integer.parseInt(st.nextToken());
	
					w = new StandardWorker(id, total, correct, wrong);
	
					wp = getPoolForName(pool);
					if (wp == null && createPools) {
						WorkerPool.createNewWorkerPool(pool, 0);
						wp = getPoolForName(pool);
					}
					wp.addWorker(w);
					Integer score = workerManager.getQualificationValue(id);
					if (pool.equals("ACTIVE")) {
						if (score != null
								&& score == StaticInformation.activePoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager.assignQualification(
								StaticInformation.scenario
										.getQualificationTypeID(), id,
								StaticInformation.activePoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.activePoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.activePoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.activePoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}
	
					} else if (pool.equals("PENDING")) {
						if (score != null
								&& score == StaticInformation.pendingPoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager
								.assignQualification(
										StaticInformation.scenario
												.getQualificationTypeID(),
										id,
										StaticInformation.pendingPoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.pendingPoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.pendingPoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.pendingPoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}
					} else if (pool.equals("BLOCKED")) {
						if (score != null
								&& score == StaticInformation.blockedPoolQualificationValue) {
							perflog.info("Worker " + id
									+ " already has the correct value.");
							line = br.readLine();
							continue;
						}
						if (!workerManager
								.assignQualification(
										StaticInformation.scenario
												.getQualificationTypeID(),
										id,
										StaticInformation.blockedPoolQualificationValue)) {
							perflog.warn("Could not assign qualification with value "
									+ StaticInformation.blockedPoolQualificationValue
									+ " to worker " + id + ".");
							perflog.info("Trying to update qualification value.");
							if (!workerManager
									.setQualificationValue(
											StaticInformation.scenario
													.getQualificationTypeID(),
											id,
											StaticInformation.blockedPoolQualificationValue)) {
								perflog.warn("Updating qualification value to "
										+ StaticInformation.blockedPoolQualificationValue
										+ " failed as well. Moving to pool \"DELETED\"");
								deleted.put(w, pool);
							}
						}
					}
					line = br.readLine();
				}
				WorkerPool del = getPoolForName("DELETED");
				for (AbstractWorker ww : deleted.keySet()) {
					perflog.info((del.addWorker(ww) ? "Added worker "
							+ ww.getWorkerId() + " to pool \"DELETED\"."
							: "Adding worker " + ww.getWorkerId()
									+ " to pool \"DELETED\" failed."));
					perflog.info((getPoolForName(deleted.get(ww)).removeWorker(
							ww) ? "Removed worker " + ww.getWorkerId()
							+ " from original pool."
							: "Could not remove worker " + ww.getWorkerId()
									+ " from original pool."));
				}
	
				return true;
			}
			
		} catch (FileNotFoundException f) {
			basiclog.error("File not found: " + file);
			return false;
		} catch (NullPointerException f) {
			basiclog.error("Pool " + pool + " does not exist");
			return false;
		} catch (NumberFormatException n) {
			basiclog.error("Invalid characters when a number was expected!");
			return false;
		} catch (Exception e) {
			basiclog.error("Could not import from file " + file
					+ " due to the following exception: " + e);
			return false;
		}
	}

}
